import PlayerConn from "./PlayerConn";
import expressWs = require("express-ws");
import Game from "../../assets/script/common/game/Game";
import { GameEvent } from "../../assets/script/common/game/event/GameEvent";
import Timer from "../../assets/script/common/core/Timer";
import { ProtoVo } from "../../assets/script/common/protocol/Protocol";

const et = GameEvent.Type

export default class GameServer {

    /** 玩家链接 */
    private _players: Map<number, PlayerConn> = new Map()
    /** websocket */
    private _ws: expressWs.Instance
    /** 游戏实例 */
    private _game: Game
    /** 计时器 */
    private _timer: Timer = new Timer()

    private _exitingPlayerIds: number[] = []
    private _updateSnakeHidMap = new Map<number, number>()

    constructor(ws: expressWs.Instance) {
        this._timer.set("test", 0)
        this._ws = ws
        this._game = new Game()
        this._game.ed.on(et.GAME_UPDATE, this, this.update)
        this._game.ed.on(et.SNAKE_SPAWN, this, e => {
            let { snake } = e
            this._updateSnakeHidMap.set(snake.id, snake.head.id)
        })
        this._game.start()
        ws.app.ws("/", (conn, req) => new PlayerConn(this, this._game, conn))

    }

    /** 每帧执行 */
    update() {
        this._timer.check("test", () => {

            let snakes: ProtoVo.IS2C_SNAKE_HID_UPDATE_SNAKE[] = []
            this._updateSnakeHidMap.forEach((hid, snakeId) => {
                snakes.push({ id: snakeId, hid })
            })
            this._players.forEach(player => {
                if (!player.isReady) {
                    return
                }
                player.sendSnake()
                player.sendHid({ snakes })
                player.sendFoods()
                player.sendSnakeNodes()
            })
            this._updateSnakeHidMap.clear()
        })
        this._exitingPlayerIds.forEach(id => {
            this._game.exit(id)
        })
        this._exitingPlayerIds = []
    }

    /** 玩家加入 */
    join(conn: PlayerConn) {
        this._players.set(conn.id, conn)
    }

    /** 玩家退出 */
    exit(id: number) {
        this._players.delete(id)
        this._exitingPlayerIds.push(id)
    }
}